def queryTagHistory(paths, startDate, endDate, columnNames=None, returnSize=-1, aggregationModeCustom=False, aggregationMode="MinMax", returnFormat="Wide", intervalHours=None, intervalMinutes=None, rangeHours=None, rangeMinutes=None, aggregationModesCustom=None, aggregationModes=None, includeBoundingValues=None, validateSCExec=None, noInterpolation=None, ignoreBadQuality=None):
	import system
	
	paths = paths.split(",")
	
	if columnNames != None:
		columnNames = columnNames.split(",")
		
	if aggregationModeCustom != None and aggregationModeCustom:
		aggregationModeParts = aggregationMode.split(";")
		aggregationMode = shared.historian.customFunction(*aggregationModeParts)
		
	if aggregationModes != None:
		if aggregationModesCustom != None:
			aggregationModesCustom = aggregationModesCustom.split(",")
		else:
			aggregationModesCustom = []
			
		aggregationModes = aggregationModes.split(",")
		for i in range(len(aggregationModes)):
			isCustom = False
			if i < len(aggregationModesCustom):
				isCustom = int(aggregationModesCustom[i])
			
			if isCustom:
				aggregationModeParts = aggregationModes[i].split(";")
				aggregationModes[i] = shared.historian.customFunction(*aggregationModeParts)
	
	return system.tag.queryTagHistory(paths=paths, startDate=startDate, endDate=endDate, columnNames=columnNames, returnSize=returnSize, aggregationMode=aggregationMode, returnFormat=returnFormat, intervalHours=intervalHours, intervalMinutes=intervalMinutes, rangeHours=rangeHours, rangeMinutes=rangeMinutes, aggregationModes=aggregationModes, includeBoundingValues=includeBoundingValues, validateSCExec=validateSCExec, noInterpolation=noInterpolation, ignoreBadQuality=ignoreBadQuality)
	
def queryTagCalculations(paths, startDate, endDate, columnNames=None, rangeHours=None, rangeMinutes=None, calculationsCustom=None, calculations=None, includeBoundingValues=None, validateSCExec=None, noInterpolation=None, ignoreBadQuality=None):
	import system
	
	paths = paths.split(",")
		
	if columnNames != None:
		columnNames = columnNames.split(",")
		
	if calculations != None:
		if calculationsCustom != None:
			calculationsCustom = calculationsCustom.split(",")
		else:
			calculationsCustom = []
			
		calculations = calculations.split(",")
		for i in range(len(calculations)):
			isCustom = False
			if i < len(calculationsCustom):
				isCustom = int(calculationsCustom[i])
			
			if isCustom:
				calculationsParts = calculations[i].split(";")
				calculations[i] = shared.historian.customFunction(*calculationsParts)
	
	return system.tag.queryTagCalculations(paths=paths, startDate=startDate, endDate=endDate, aliases=columnNames, calculations=calculations, rangeHours=rangeHours, rangeMinutes=rangeMinutes, includeBoundingValues=includeBoundingValues, validateSCExec=validateSCExec, noInterpolation=noInterpolation, ignoreBadQuality=ignoreBadQuality)

def customFunction(*args):
	functionName = args[0]
	argsStr = ", ".join([str(args[i]) for i in range(1, len(args))])
	return """python:def wrapper(qval, interpolated, finished, blockContext, queryContext):
	return shared.historian.%s(qval, interpolated, finished, blockContext, queryContext, %s)""" % (functionName, argsStr)

def PercentInRange(qval, interpolated, finished, blockContext, queryContext, rangeLow, rangeHigh):
	prevTimeInRange = blockContext.getOrDefault("prevTimeInRange", None)
	
	if qval.quality.isGood():
		currentTime = qval.timestamp.getTime()
		currentValue = qval.value
		if currentValue >= rangeLow and currentValue <= rangeHigh:
			if prevTimeInRange == None:
				blockContext["prevTimeInRange"] = currentTime
		else:
			if prevTimeInRange != None:
				timeDiff = blockContext.getOrDefault("timeDiff", 0.0)
				blockContext["timeDiff"] = timeDiff + (currentTime - long(prevTimeInRange))
				blockContext["prevTimeInRange"] = None
	
	if finished:
		blockStart = blockContext.blockStart
		blockEnd = blockContext.blockEnd
		blockDiff = float(blockEnd - blockStart )
		timeDiff = blockContext.getOrDefault("timeDiff", 0.0)
		prevTimeInRange = blockContext.getOrDefault("prevTimeInRange", None)
		if prevTimeInRange != None:
			timeDiff += (blockEnd - long(prevTimeInRange))
		
		if blockDiff > 0:
			return timeDiff / blockDiff * 100.0
		else:
			return 0.0

def millisecondsToTime(ms):
	seconds = (ms / 1000) % 60
	minutes = (ms / (1000 * 60)) % 60
	hours = (ms / (1000 * 60 * 60)) % 24
	return "%02d:%02d:%02d" % (hours, minutes, seconds)
			
def TimeSpentInState(qval, interpolated, finished, blockContext, queryContext, state):	
	prevTimeInState = blockContext.getOrDefault("prevTimeInState", None)
			
	if qval.quality.isGood():
		currentTime = qval.timestamp.getTime()
		currentValue = qval.value
		if currentValue == state:
			if prevTimeInState == None:
				blockContext["prevTimeInState"] = currentTime
		else:
			if prevTimeInState != None:
				timeDiff = blockContext.getOrDefault("timeDiff", 0.0)
				blockContext["timeDiff"] = timeDiff + (currentTime - long(prevTimeInState))
				blockContext["prevTimeInState"] = None
	
	if finished:
		blockEnd = blockContext.blockEnd
		timeDiff = blockContext.getOrDefault("timeDiff", 0.0)
		prevTimeInState = blockContext.getOrDefault("prevTimeInState", None)
		if prevTimeInState != None:
			timeDiff += (blockEnd - long(prevTimeInState))
		
		return timeDiff
		
def ExceedValueCount(qval, interpolated, finished, blockContext, queryContext, exceedValue):	
	prevExceed = blockContext.getOrDefault("prevExceed", False)
			
	if qval.quality.isGood():
		currentTime = qval.timestamp.getTime()
		currentValue = qval.value
		if currentValue > exceedValue:
			if not prevExceed:
				exceedCount = blockContext.getOrDefault("exceedCount", 0)
				blockContext["exceedCount"] = exceedCount + 1
			blockContext["prevExceed"] = True
		else:
			blockContext["prevExceed"] = False
	
	if finished:
		return blockContext.getOrDefault("exceedCount", 0)